/*
 * Copyright ©2015-2021 Jaemon. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.gitee.jaemon.spring.adorner.support;

import io.gitee.jaemon.spring.adorner.AdornerConstants;
import io.gitee.jaemon.spring.adorner.core.AdornerApplicationContext;
import io.gitee.jaemon.spring.adorner.core.AdornerDoclet;
import io.gitee.jaemon.spring.adorner.core.NoteScanner;
import io.gitee.jaemon.spring.adorner.type.DocScanner;
import io.gitee.jaemon.spring.adorner.exception.AdornerException;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.stream.Collectors;

import static io.gitee.jaemon.spring.adorner.util.LoggerHelper.error;

/**
 * Adorner注释扫描器
 *
 * @author Jaemon
 * @since 1.0
 */
public class AdornerNoteScanner implements NoteScanner {
    private static final String enconding = System.getProperty("file.encoding") == null ?
            AdornerConstants.DEFAULT_CHARSET : System.getProperty("file.encoding");
    private static final String NOTICE_FILE_NAME = "adorner_note_console.log";
    private static final String WARN_FILE_NAME = "adorner_note_warn.log";
    private static final String ERROR_FILE_NAME = "adorner_note_error.log";


    @Override
    public boolean doScan(AdornerApplicationContext context) throws AdornerException {
        try {
            return scanner(context);
        } catch (FileNotFoundException e) {
            error("扫描文档注释[%s]异常, %s", context.docScanner().toString(), e.getMessage());
            return false;
        }
    }

    /**
     * 扫描器
     *
     * @param context
     *      Adorner上下文
     * @throws FileNotFoundException
     *      ex
     * @return
     *      true | false
     */
    public boolean scanner(AdornerApplicationContext context) throws FileNotFoundException {
        DocScanner doc = context.docScanner();
        if (doc == null || doc.getPackages() == null || doc.getPackages().isEmpty()) {
            return false;
        }
        String programName = "Spring-Adorner";
        String prefixPath = context.isLogger() ? context.logpath() : AdornerConstants.EMPTY;
        // 用于接收错误消息的PrintWriter
        File errorFile = new File(prefixPath + ERROR_FILE_NAME);
        // 用于接收错误消息
        File warnFile = new File(prefixPath + WARN_FILE_NAME);
        // 用于接收控制台消息
        File noticeFile = new File(prefixPath + NOTICE_FILE_NAME);

        try (
                PrintWriter errWriter = new PrintWriter(errorFile);
                PrintWriter warnWriter = new PrintWriter(warnFile);
                PrintWriter noticeWriter = new PrintWriter(noticeFile)
        ) {
            // 完全限定的类名
            String defaultDocletClassName = AdornerDoclet.class.getName();
            // 指定要递归加载的子程序包
            String scanPackages = doc.getPackages().stream().collect(Collectors.joining(":"));
            // 源码文件路径
            String classPath = doc.getClassPath();

            // 命令行参数
            String[] options = new String[] {
                    // -doclet 指定自己的docLet类名, 否则使用默认生成html
//                   "-doclet", defaultDocletClassName,
                    "-private",
                    // -encoding 指定源码文件的编码格式
                    "-encoding", enconding,
                    // 输出有关 Javadoc 正在执行的操作的信息
                    "-verbose",
                    // -classpath 参数指定 源码文件及依赖库的class位置, 不提供则无法获取到依赖库的注释信息
                    "-classpath", classPath,
                    // 设置要输出的最大警告数, 错误数
//                "-Xmaxwarns", "1000", "-Xmaxerrs", "1000",
                    // 指定要递归加载的子程序包
                    "-subpackages", scanPackages
            };

            com.sun.tools.javadoc.Main.execute(
                    programName,
                    errWriter, warnWriter, noticeWriter,
                    defaultDocletClassName,
                    options
            );

            AdornerDoclet.scanner();
        } finally {
            if (!context.isLogger()) {
                if (errorFile.exists()) {
                    errorFile.delete();
                }

                if (warnFile.exists()) {
                    warnFile.delete();
                }

                if (noticeFile.exists()) {
                    noticeFile.delete();
                }
            }
            return true;
        }


    }

}
